//Copyright (C) 2011 Ron Coleman. Contact: ronncoleman@gmail.com
//You should have received a copy of the GNU General Public License
//along with this library; if not, write to the Free Software
//Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
package bj.actor

import bj.hkeeping.PlayerMsg
import bj.hkeeping.SetBank
import bj.hkeeping.ClientBet
import bj.hkeeping.GetPid
import scala.actors.Actor
import bj.util.Logs
import org.apache.log4j.Logger
import org.apache.log4j.Level
import org.apache.log4j.PropertyConfigurator
import scala.actors.Actor
import Actor._
import scala.actors.remote.RemoteActor.{ alive, register }
import scala.actors.remote.RemoteActor
import scala.actors.remote.Node
import scala.actors.remote.NetKernel
import scala.actors.AbstractActor
import scala.actors._
import scala.actors.Actor._
import scala.actors.remote._
import scala.actors.remote.RemoteActor._
import java.net._

case class HitRequest(remotePid: Int)

class GameServer(serverName: Symbol, serverAddr: String, serverPort: Int) extends Actor with Logs {
  var players       = List[Player]()
  var botPlayers    = List[BotPlayer](new BotPlayer("RonBot0", 1000, 100), new BotPlayer("RonBot1", 1000, 25), new BotPlayer("RonBot2", 1000, 5))
  var humanPlayers  = List[HumanPlayer]()
  var remotePlayers = List[RemotePlayer]()
   	  players       = botPlayers
  
  
  var aHumanPlayer:  HumanPlayer  = null
  var aRemotePlayer: RemotePlayer = null

  var Pid = -1

  /** Arrives here on start */
  def act {
    println("HouseServer started!")
    // Declare the port I'm listening on
    alive(serverPort)

    // Register me
    register(serverName, self)
    
    loop {
      react {
        // Receives a message
        case PlayerMsg(playerName) => createPlayer(PlayerMsg(playerName))
          sender ! GetPid(aHumanPlayer.pid)
          debug("Sending back PID to PlayerGUI. PID = " + aHumanPlayer.pid)

        case SetBank(playerId: Int, amount: Double) => players(playerId).setBankRoll(amount)
          val bankAmt = players(playerId).bankroll;
        	  debug(players(playerId) + " ===> " + " Bankroll = " + bankAmt)
        
        case ClientBet(clientPid, clientBetAmount) => if(updateBet(clientBetAmount, clientPid)) startPlayers  
      }
    }
  } //End act{}
  
  def createPlayer(msg: PlayerMsg) {
    
    aHumanPlayer = new HumanPlayer(msg.playerName, 0.0, 0.0)
    
    addAPlayer(aHumanPlayer)
    debug("Human Player " + aHumanPlayer + " created")
  }

  private def addAPlayer(aPlayer: Player) {
    players = players ::: List[Player](aPlayer)
    humanPlayers = humanPlayers ::: List[HumanPlayer](aHumanPlayer)
    remotePlayers = remotePlayers ::: List[RemotePlayer](aRemotePlayer)
    
    debug("Player ID = " + players(players.size-1).pid + " added to playersList: " + players)
  }
  
  def updateBet(amt: Double, playerId: Int): Boolean = {
    if (amt <= players(playerId).bankroll) {
    //if (amt <= players(players.size - 1).bankroll) {
      players(playerId).setBet(amt);
      //players(players.size - 1).setBet(amt);
      val betAmt = players(playerId).betAmt;
      //val betAmt = players(players.size - 1).betAmt;
      debug(players(playerId) + " ===> " + " Bet = " + betAmt)
      //debug(players(players.size - 1) + " ===> " + " Bet = " + betAmt)
      return true
    }
    debug("Bet="+amt + " > Player's=" + players(playerId) + " BankRoll=" + players(playerId).bankroll)
    debug("Enter an amount <= to your BankRoll!!!")
    //Send NoOk msg back to player
    return false
  }
  
  def startPlayers {
    debug("starting players")
    Player.start(players)
    Thread.sleep(1000)
    debug("There are: (" + players.size + ") Player(s)")
    houseGo
  }

  def houseGo {
    Thread.sleep(1000)

    debug("telling house go")
    House ! Go
  }
} //End class GameServer

object GameServer extends Logs {
  /**  Logger.getLogger(getClass).setLevel(Level.DEBUG) */
  
  PropertyConfigurator.configure("log4j.properties")
  
  RemoteActor.classLoader = getClass().getClassLoader()
  /** My service name */
  val SERVER_NAME = 'jackBlack_Casino
    
  /** My service port */
  val SERVER_PORT = 14500
  
  val localHost = InetAddress.getLocalHost
  val gameServerAddr = localHost.getHostAddress
    
  val gameServer = new GameServer(SERVER_NAME, gameServerAddr,SERVER_PORT).start
  println("GameService " + SERVER_NAME + " Started @ " + gameServerAddr + " on Port: " + SERVER_PORT)
  
  def startGameServer {
    gameServer.start
  
    debug("Starting the house")
    House.start

    Thread.sleep(1000)
  }
  
  def main(): Unit = {
    startGameServer
  }
}